package models

import (
	"bigdevops/src/common"
	"fmt"
	"github.com/prometheus/alertmanager/template"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"strings"
)

// 采集任务 和机器的关系
// 1对多 机器只能属于1个采集任务
// 新建采集任务 就需要填入ip
// 主配置文件池
// job 对象 机器：ip+port
//
//	2 k8s 的服务发现：集群外部采集
//
// D:\nyy_work\go_path\src\github.com\prometheus\prometheus\model\rulefmt\rulefmt.go
// 对于重复告警fingerprint 是唯一的标识 event_id
// startat 是不会变的，endat为空说明 还在触发中
// 有必要记录一下发送次数
type MonitorAlertEvent struct {
	Model              // 不用每次写ID 和 createAt了
	AlertName   string `json:"alertName"`
	Fingerprint string `json:"fingerprint" validate:"required,min=1,max=50" gorm:"uniqueIndex;type:varchar(100);comment:告警unique id eventId" `
	Status      string `json:"status" gorm:"comment: 告警状态：告警中，已屏蔽，已认领，已恢复"`
	RuleId      uint   `json:"ruleId"`
	SendGroupId uint   `json:"sendGroupId"`
	EventTimes  int    `json:"eventTimes" gorm:"comment: 触发次数"`
	SilenceId   string `json:"silenceId" gorm:"comment: alertmanager返回的静默id"`

	RenLingUserId uint        `json:"renLingUserId" gorm:"comment: 是谁认领了告警"`
	Labels        StringArray `json:"labels" gorm:"comment: 标签组 key=v ,scrape_ip=1.1.1.1 "`
	// D:\nyy_work\go_path\src\github.com\prometheus\prometheus\config\config.go
	// 下面是global段

	// 公共的
	Key           string            `json:"key" gorm:"-"`           //给前端表格
	AlertRuleName string            `json:"alertRuleName" gorm:"-"` //给前端表格
	SendGroupName string            `json:"sendGroupName" gorm:"-"` //给前端表格
	Alert         template.Alert    `json:"alert" gorm:"-"`
	SendGroup     *MonitorSendGroup `json:"sendGroup" gorm:"-"`
	RenLingUser   *User             `json:"renLingUser" gorm:"-"`
	Rule          *MonitorAlertRule `json:"rule" gorm:"-"`

	LabelsM      map[string]string `json:"labelsM" gorm:"-"`
	AnnotationsM map[string]string `json:"annotationsM" gorm:"-"`
}

func (obj *MonitorAlertEvent) Create() error {
	return Db.Create(obj).Error

}
func (obj *MonitorAlertEvent) DeleteOne() error {

	return Db.Select(clause.Associations).Unscoped().Delete(obj).Error

}

func (obj *MonitorAlertEvent) CreateOne() error {
	return Db.Create(obj).Error

}

// 首先根据 GetMonitorAlertEventByFingerprintId 查找这个event
// 如果没有 就创建 ，如果有 更新状态和次数
func (obj *MonitorAlertEvent) UpdateOrCreateOne() error {

	dbObj, err := GetMonitorAlertEventByFingerprintId(obj.Fingerprint)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			// 说明记录不存在，那么应该新建
			obj.EventTimes = 1
			return obj.CreateOne()
		}
		fmt.Println("UpdateOrCreateOne,err:", err)
		return err
	}
	if dbObj.Status != common.MONITOR_ALERT_STATUS_RENLING {
		dbObj.Status = obj.Status
	}
	dbObj.EventTimes++
	return dbObj.UpdateOne()
}

func (obj *MonitorAlertEvent) UpdateOne() error {
	return Db.Where("id = ?", obj.ID).Updates(obj).Error

}

//func (obj *MonitorAlertEvent) ValidateRelabelConfigsYamlString() error {
//	var relabelConfigsObj []*relabel.Config
//	return yaml.Unmarshal([]byte(obj.RelabelConfigsYamlString), &relabelConfigsObj)
//
//}

func (obj *MonitorAlertEvent) GenMapFromKvs() map[string]string {

	labelsM := map[string]string{}
	for _, i := range obj.Labels {
		kvs := strings.Split(i, "=")
		if len(kvs) != 2 {
			continue
		}
		k := kvs[0]
		v := kvs[1]
		labelsM[k] = v
	}
	obj.LabelsM = labelsM
	return labelsM

}

func (obj *MonitorAlertEvent) FillFrontAllData() {

	//dbPoll, _ := GetMonitorScrapePoolById(int(obj.PoolId))
	//if dbPoll != nil {
	//	obj.PoolName = dbPoll.Name
	//}

	obj.CreatedTime = common.TimeFormat(obj.CreatedAt)
	obj.UpdatedTime = common.TimeFormat(obj.UpdatedAt)

	obj.Key = fmt.Sprintf("%d", obj.ID)
	alertRule, _ := GetMonitorAlertRuleById(int(obj.RuleId))
	sendGroup, _ := GetMonitorSendGroupById(int(obj.SendGroupId))
	renLingUser, _ := GetUserById(int(obj.RenLingUserId))
	//log.Printf("FillFrontAllData打印:%v %v", renLingUser, err)
	obj.RenLingUser = renLingUser
	obj.AlertRuleName = alertRule.Name
	obj.SendGroupName = sendGroup.Name
	obj.SendGroup = sendGroup

	//obj.LabelsM = obj.GenMapFromKvs(obj.Labels)
	// 绑定发送组标签
	//obj.LabelsM[common.MONITOR_ALERT_MATCH_KEY] = fmt.Sprintf("%d", obj.SendGroupId)
	//obj.AnnotationsM = obj.GenMapFromKvs(obj.Annotations)

	//ids := []int{}
	//for _, id := range obj.TreeNodeIds {
	//	idInt, _ := strconv.Atoi(id)
	//	ids = append(ids, idInt)
	//}
	//obj.TreeNodeIdInts = ids

}
func GetMonitorAlertEventAll() (objs []*MonitorAlertEvent, err error) {
	err = Db.Find(&objs).Error
	return
}

func (obj *MonitorAlertEvent) SendImMessageToQunByEvent(msg, url string, logger *zap.Logger, tw int) {
	obj.FillFrontAllData()
	if obj.SendGroup == nil {
		return
	}
	// 拼接im 消息发送

	feishuTextJsonString := fmt.Sprintf(`

{
    "msg_type": "text",
    "content": {
        "text": "%s"
    }
}`, msg)
	url = fmt.Sprintf("%s/%s", url, obj.SendGroup.FeishuQunRobotToken)
	emptyMap := map[string]string{}
	bodyBytes, err := common.PostWithJsonString(logger, "SendImMessageToQunByEvent", tw, url, feishuTextJsonString, emptyMap, emptyMap)
	if err != nil {
		logger.Error("SendImMessageToQunByEvent.发送飞书群聊卡片消息失败",
			zap.Error(err),
			zap.Any("结果", string(bodyBytes)),
		)
	}
	logger.Info("SendImMessageToQunByEvent.发送飞书群聊卡片消息成功",
		zap.Any("结果", string(bodyBytes)),
	)

}

func GetMonitorAlertEventCount() int {
	var count int64
	Db.Table("form_designs").Count(&count)
	return int(count)
}

func GetMonitorAlertEventByLevel(level int) (objs []*MonitorAlertEvent, err error) {
	err = Db.Where("level = ?", level).Preload("OpsAdmins").Find(&objs).Error
	return
}

// select * from ecs where
func GetMonitorAlertEventByIdsWithLimitOffset(ids []int, limit, offset int) (objs []*MonitorAlertEvent, err error) {
	err = Db.Limit(limit).Offset(offset).Find(&objs, ids).Error
	return
}

// 查询这个节点池管理的采集Job
func GetMonitorAlertEventByFingerprintId(fingerprint string) (obj *MonitorAlertEvent, err error) {

	err = Db.Where("fingerprint= ?", fingerprint).First(&obj).Error
	return

}

func GetMonitorAlertEventById(id int) (*MonitorAlertEvent, error) {

	var dbObj MonitorAlertEvent
	err := Db.Where("id = ?", id).First(&dbObj).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("MonitorAlertEvent不存在")
		}
		return nil, fmt.Errorf("数据库错误:%w", err)
	}
	return &dbObj, nil

}
